package qqmeeting

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"strconv"
	"time"
)

type Client struct {
	config Config
}

func NewClient(config Config) *Client {
	return &Client{config: config}
}

func (c *Client) SetConfig(config Config) {
	c.config = config
}

func (c *Client) POST(uri string, body interface{}) (statusCode int, content []byte, err error) {
	//创建header
	requestBody, _ := json.Marshal(body)
	headers, err := c.createHeaders("POST", uri, requestBody)
	if err != nil {
		return
	}
	reqURL := TM_HOST + uri
	reader := bytes.NewReader(requestBody)
	request, err := http.NewRequest("POST", reqURL, reader)
	if err != nil {
		return
	}
	//设置header
	request.Header.Set("Content-Type", "application/json;charset=UTF-8")
	for k, v := range headers {
		request.Header[k] = []string{v}
	}

	//请求
	tr := new(http.Transport)
	tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: false}
	client := &http.Client{Transport: tr}
	resp, err := client.Do(request)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	//读取内容
	statusCode = resp.StatusCode
	content, err = ioutil.ReadAll(resp.Body)

	return
}
func (c *Client) PUT(uri string, body interface{}) (statusCode int, content []byte, err error) {
	//创建header
	requestBody, _ := json.Marshal(body)
	headers, err := c.createHeaders("PUT", uri, requestBody)
	if err != nil {
		return
	}
	reqURL := TM_HOST + uri
	reader := bytes.NewReader(requestBody)
	request, err := http.NewRequest("PUT", reqURL, reader)
	if err != nil {
		return
	}
	//设置header
	request.Header.Set("Content-Type", "application/json;charset=UTF-8")
	for k, v := range headers {
		request.Header[k] = []string{v}
	}
	//请求
	tr := new(http.Transport)
	tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: false}
	client := &http.Client{Transport: tr}
	resp, err := client.Do(request)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	//读取内容
	statusCode = resp.StatusCode
	content, err = ioutil.ReadAll(resp.Body)

	return
}

func (c *Client) GET(uri string) (statusCode int, content []byte, err error) {
	//创建header
	requestBody := []byte{}
	headers, err := c.createHeaders("GET", uri, requestBody)
	if err != nil {
		return
	}

	reader := bytes.NewReader(requestBody)
	request, err := http.NewRequest("GET", TM_HOST+uri, reader)
	if err != nil {
		return
	}
	//设置header
	request.Header.Set("Content-Type", "application/json;charset=UTF-8")
	for k, v := range headers {
		request.Header[k] = []string{v}
	}
	//请求
	tr := new(http.Transport)
	tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: false}
	client := &http.Client{Transport: tr}
	resp, err := client.Do(request)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	//读取内容
	statusCode = resp.StatusCode
	content, err = ioutil.ReadAll(resp.Body)

	return
}

func (c *Client) createHeaders(httpMethod, uri string, body []byte) (map[string]string, error) {
	//创建header
	nonce := strconv.Itoa(createNonce())
	timestamp := strconv.FormatInt(time.Now().Unix(), 10)
	headers := make(map[string]string)
	headers["X-TC-Key"] = c.config.SecretID
	headers["X-TC-Timestamp"] = timestamp
	headers["X-TC-Nonce"] = nonce
	//签名
	headerStr := fmt.Sprintf("X-TC-Key=%s&X-TC-Nonce=%s&X-TC-Timestamp=%s", c.config.SecretID, nonce, timestamp)
	sig := c.createSign(httpMethod, headerStr, uri, body)
	headers["X-TC-Signature"] = sig

	if VERSION != "" {
		headers["X-TC-Version"] = VERSION
	}
	if c.config.Token != "" {
		headers["X-TC-Token"] = c.config.Token
	}
	if c.config.Appid != "" {
		headers["AppId"] = c.config.Appid
	}
	if c.config.Sdkid != "" {
		headers["SdkId"] = c.config.Sdkid
	}
	return headers, nil
}
func (c *Client) createSign(httpMethod, headerStr, uri string, body []byte) string {
	//拼接字符串
	buff := bytes.NewBuffer([]byte{})
	//write method
	buff.WriteString(httpMethod)
	buff.WriteByte('\n')
	// write header
	buff.WriteString(headerStr)
	buff.WriteByte('\n')
	//write uri
	buff.WriteString(uri)
	buff.WriteByte('\n')
	//write body
	buff.Write(body)

	return Sign(buff.Bytes(), c.config.SecretKey)
}

// createNonce 创建随机整数
func createNonce() int {
	rand.Seed(time.Now().UnixNano())
	return rand.Intn(999999)
}
